﻿' ******************************************************************************
' ** 
' **  Yahoo! Managed
' **  Written by Marius Häusler 2011
' **  It would be pleasant, if you contact me when you are using this code.
' **  Contact: YahooFinanceManaged@gmail.com
' **  Project Home: http://code.google.com/p/yahoo-finance-managed/
' **  
' ******************************************************************************
' **  
' **  Copyright 2011 Marius Häusler
' **  
' **  Licensed under the Apache License, Version 2.0 (the "License");
' **  you may not use this file except in compliance with the License.
' **  You may obtain a copy of the License at
' **  
' **    http://www.apache.org/licenses/LICENSE-2.0
' **  
' **  Unless required by applicable law or agreed to in writing, software
' **  distributed under the License is distributed on an "AS IS" BASIS,
' **  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' **  See the License for the specific language governing permissions and
' **  limitations under the License.
' ** 
' ******************************************************************************


Namespace YahooManaged.Search



    Friend Class SearchHelper
        Inherits MyHelper

        Public Function BossV2SearchUrl(ByVal clientOptions As BOSS.API.SearchClientOptions, ByVal services() As BOSS.API.SearchOptions) As String

            If clientOptions.ConsumerKey = String.Empty Then Throw New ArgumentException("The OAuth Consumer Key is empty.", "clientOptions.ConsumerKey")
            If clientOptions.ConsumerSecret Is Nothing OrElse clientOptions.ConsumerSecret.Length = 0 Then Throw New ArgumentException("The OAuth Consumer Secret is null or empty.", "clientOptions.ConsumerSecret")
            If services Is Nothing OrElse services.Length = 0 Then Throw New ArgumentNullException("services", "There are no passed services for searching.")

            Dim url As New Text.StringBuilder()
            If clientOptions.HttpsUsed Then
                url.Append("https")
            Else
                url.Append("http")
            End If
            url.Append("://yboss.yahooapis.com/ysearch/")

            For Each serv In services
                url.Append(serv.ServiceName & ",")
            Next
            url.Remove(url.Length - 1, 1)

            url.Append("?")

            For Each serv In services
                If TypeOf serv Is BOSS.API.WebSearchOptions Then
                    url.Append(Me.GetWebSearchParameters(CType(serv, BOSS.API.WebSearchOptions)))
                ElseIf TypeOf serv Is BOSS.API.ImageSearchOptions Then
                    url.Append(Me.GetImageSearchParameters(CType(serv, BOSS.API.ImageSearchOptions)))
                ElseIf TypeOf serv Is BOSS.API.NewsSearchOptions Then
                    url.Append(Me.GetNewsSearchParameters(CType(serv, BOSS.API.NewsSearchOptions)))
                End If
            Next

            url.Append("&format=xml")

            Return url.ToString
        End Function

        Private Function GetUniversalParameters(ByVal opt As BOSS.API.SearchOptions) As String
            Dim res As New Text.StringBuilder
            With opt
                res.AppendFormat("{0}.q={1}", .ServiceName, .QueryText)
                If .Start > 0 Then
                    res.Append("&" & .ServiceName & ".start=")
                    res.Append(Math.Max(0, HigherOrValue(.Start, 0, 0)).ToString)
                End If

                res.Append("&" & .ServiceName & ".count=")
                res.Append(Math.Max(1, HigherOrValue(.Count, 0, 10)).ToString)

                If .Culture IsNot Nothing AndAlso Not (.Culture.Language = Language.en And .Culture.Country = Country.US) Then
                    res.Append("&" & .ServiceName & "." & Me.BossV2CultureParameters(.Culture))
                End If

                If .RestrictedSites IsNot Nothing AndAlso .RestrictedSites.Count > 0 Then
                    res.Append("&" & .ServiceName & ".sites=")
                    For Each site As Uri In .RestrictedSites
                        res.Append(site.Host & ",")
                    Next
                    res.Remove(res.Length - 1, 1)
                End If

            End With
            Return res.ToString
        End Function

        Private Function GetWebSearchParameters(ByVal options As BOSS.API.WebSearchOptions) As String
            If options Is Nothing Then Throw New ArgumentNullException("options", "WebSearchOptions is null.")
            Dim params As New Text.StringBuilder
            With options
                params.Append(Me.GetUniversalParameters(options))
                If Not .AllowAdultContent Then params.Append("&filter=-porn")
                If .LongAbstract Then params.Append("&abstract=long")
                If .RestrictedTitle <> String.Empty Then params.Append("&title=" & .RestrictedTitle)
                If .RestrictedUrl <> String.Empty Then params.Append("&url=" & .RestrictedUrl)
                If Not .HtmlTaggedText Then params.Append("&style=raw")

                If (.AllowedFileTypes IsNot Nothing AndAlso .AllowedFileTypes.Length > 0) Or (.AllowedFileGroups IsNot Nothing AndAlso .AllowedFileGroups.Length > 0) Then
                    params.Append("&type=")
                    Dim lst As New List(Of WebFileType)
                    For Each grp In .AllowedFileGroups
                        For Each t As WebFileType In grp.FileTypes
                            If Not lst.Contains(t) Then lst.Add(t)
                        Next
                    Next
                    For Each t In .AllowedFileTypes
                        If Not lst.Contains(t) Then lst.Add(t)
                    Next
                    For Each t In lst
                        params.Append(t.ToString.ToLower)
                        If lst.IndexOf(t) <> lst.Count - 1 Then params.Append(",")
                    Next
                End If
                If .SearchMonkey Or .LanguageInfo Then
                    params.Append("&view=")
                    If .SearchMonkey Then params.Append("smfeed,")
                    If .LanguageInfo Then params.Append("language,")
                    params.Remove(params.Length - 1, 1)
                End If

            End With
            Return params.ToString
        End Function

        Private Function GetImageSearchParameters(ByVal options As BOSS.API.ImageSearchOptions) As String
            If options Is Nothing Then Throw New ArgumentNullException("options", "ImageSearchOptions is null.")
            Dim params As New Text.StringBuilder
            With options
                params.Append(Me.GetUniversalParameters(options))
                If .AllowAdultContent Then params.Append("&filter=no")
                If .Dimensions <> BOSS.ImageSearchDimensions.All Then params.Append("&dimensions=" & .Dimensions.ToString.ToLower)
                If .RefererUrl IsNot Nothing Then params.Append("&refererurl=" & .RefererUrl.ToString)
                If .Url IsNot Nothing Then params.Append("&url=" & .Url.ToString)
            End With
            Return params.ToString
        End Function

        Private Function GetNewsSearchParameters(ByVal options As BOSS.API.NewsSearchOptions) As String
            If options Is Nothing Then Throw New ArgumentNullException("options", "NewsSearchOptions is null.")
            Dim params As New Text.StringBuilder
            With options
                params.Append(Me.GetUniversalParameters(options))
                params.Append("&age=")
                If Date.Now.AddSeconds(-60) < .LatestDate Then
                    params.Append(GetTimeSpanString(.EarliestDate))
                Else
                    params.Append(GetTimeSpanString(.LatestDate))
                    params.Append("-")
                    params.Append(GetTimeSpanString(.EarliestDate))
                End If
                If .Sorting <> BOSS.NewsSortRanking.None Then
                    params.Append("&sort=")
                    Select Case .Sorting
                        Case BOSS.NewsSortRanking.AsiaRanking : params.Append("asiarank")
                        Case BOSS.NewsSortRanking.EuRanking : params.Append("eurank")
                        Case BOSS.NewsSortRanking.UsRanking : params.Append("usrank")
                        Case Else : params.Append("date")
                    End Select
                End If
                If .RestrictedTitle <> String.Empty Then params.Append("&title=" & .RestrictedTitle)
                If .RestrictedUrl <> String.Empty Then params.Append("&title=" & .RestrictedUrl)
            End With
            Return params.ToString
        End Function



        Private Function GetSpellingSearchParameters(ByVal options As BOSS.API.WebSearchOptions) As String
            If options Is Nothing Then Throw New ArgumentNullException("options", "SpellingSearchOptions is null.")
            Dim params As New Text.StringBuilder
            With options
                params.Append(Me.GetUniversalParameters(options))
            End With
            Return params.ToString
        End Function

        Private Function BossV2CultureParameters(ByVal cult As Culture) As String
            If cult Is Nothing Then Throw New ArgumentNullException("cult", "Culture must have a value")
            Return String.Format("market={0}-{1}", cult.Language.ToString, cult.Country.ToString.ToLower)
        End Function

        Private Function GetTimeSpanString(ByVal d As Date) As String
            Dim now As Date = Date.Now
            Dim tDate As Date = Date.Now
            If now > d Then tDate = d
            Dim span As TimeSpan = now - tDate
            If span.TotalSeconds < 1000 Then
                Return Convert.ToInt32(span.TotalSeconds).ToString & "s"c
            Else
                If span.TotalMinutes < 1000 Then
                    Return Convert.ToInt32(span.TotalMinutes).ToString & "m"c
                Else
                    If span.TotalHours < 1000 Then
                        Return Convert.ToInt32(span.TotalHours).ToString & "h"c
                    Else
                        If span.TotalDays < 1000 Then
                            Return Convert.ToInt32(span.TotalDays).ToString & "d"c
                        Else
                            If span.TotalDays / 7 < 1000 Then
                                Return Convert.ToInt32(span.TotalDays / 7).ToString & "w"c
                            Else
                                Return "1000w"
                            End If
                        End If
                    End If
                End If
            End If
        End Function

        Private Function HigherOrValue(ByVal value As Integer, ByVal thenValue As Integer, ByVal elseValue As Integer) As Integer
            If value > thenValue Then : Return value
            Else : Return elseValue
            End If
        End Function

    End Class

End Namespace